
package livro.model;

import bibliinfo.FrameMain;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import usuario.model.UsuarioDao;
import utilitarios.Conexao;
import utilitarios.Dao;

public class LivroDao extends Dao<Object, Object, Object, Object> {
    
    public void create(Livro livro, List<LivroExe> lista, Object c, Object d) {
        
        Connection con = Conexao.getConnection();        
        try{
            
            con.setAutoCommit(false);
            String sql = "insert into livro (isbn, titulo, autor, editora, ativo) values (?,?,?,?,?)";
            try(PreparedStatement stm = con.prepareStatement(sql)){
                stm.setString(1, livro.getISBN());
                stm.setString(2, livro.getTitulo());
                stm.setString(3, livro.getAutor());
                stm.setString(4, livro.getEditora());
                stm.setBoolean(5, livro.getAtivo());
                
                stm.executeUpdate();
            }           
            
            sql = "insert into livro_exe (isbn, num_seq, emprestado, pode_emp) values (?,?,?,?)";
            try(PreparedStatement stm = con.prepareStatement(sql)){
                for(LivroExe livroExe : lista){
                    stm.setString(1, livroExe.getISBN());
                    stm.setInt(2, livroExe.getNumSequencia());
                    stm.setBoolean(3, livroExe.getEmprestado());
                    stm.setBoolean(4, livroExe.getPodeEmprestar());
                    
                    stm.executeUpdate();
                }
            }            
            con.commit();            
            JOptionPane.showMessageDialog(FrameMain.bookFrameCad, "Os dados foram cadastrados com sucesso", "Sucesso", 1);
        }catch(Exception e){
            try{
                con.rollback();
                String erro = "Houve um erro ao gravar os dados do livro no banco de dados";
                JOptionPane.showMessageDialog(FrameMain.bookFrameCad, erro, "Erro", 0);
                e.printStackTrace();
            }catch(SQLException ex){
                Logger.getLogger(LivroDao.class.getName()).log(Level.SEVERE, null, ex);
            }            
        }
    }

    @Override
    public List readA() {        
        List<Livro> listaLivro = new ArrayList<>();
        Connection con = Conexao.getConnection();
        String sql = "select * from livro;";        
        try(PreparedStatement stm = con.prepareStatement(sql);
            ResultSet resultado = stm.executeQuery()){
            
            while(resultado.next() == true){
                Livro l = new Livro();
                l.setISBN(resultado.getString(1));
                l.setTitulo(resultado.getString(2));
                l.setAutor(resultado.getString(3));
                l.setEditora(resultado.getString(4));
                l.setAtivo(resultado.getBoolean(5));
                
                listaLivro.add(l);
            }          
            
        }catch(SQLException e){
                String erro = "Houve um erro ao ler as informações do Banco de Dados";
                JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, erro, "Erro", 0);
                e.printStackTrace();
        }    
        return listaLivro;
    }   

    @Override
    public List readB() {
        List<LivroExe> listaLivroReal = new ArrayList<>();
        Connection con = Conexao.getConnection();
        String sql = "select * from livro_exe";
        try(PreparedStatement stm = con.prepareStatement(sql);
                ResultSet resultado = stm.executeQuery()){
        
            while(resultado.next() == true){
                LivroExe exe = new LivroExe();
                exe.setISBN(resultado.getString(1));
                exe.setNumSequencia(resultado.getInt(2));
                exe.setEmprestado(resultado.getBoolean(3));
                exe.setPodeEmprestar(resultado.getBoolean(4));
                
                listaLivroReal.add(exe);
            }
        }catch(Exception e){
            String erro = "Houve um erro ao ler as informações do Banco de Dados";
                JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, erro, "Erro", 0);
                e.printStackTrace();
        }
        return listaLivroReal;
    }   
    
    public List readPesquisa(String pesquisa, int i){
    
        List<Livro> livros = new ArrayList<>();
        Connection con = Conexao.getConnection();
        String sql = "";
        if(i == 1){
            sql = "select * from livro where titulo like (?)";
        }else if (i == 2){
            sql = "select * from livro where isbn like (?)";
        }        
        try(PreparedStatement stm = con.prepareStatement(sql)){
            stm.setString(1, pesquisa);
            ResultSet resultado = stm.executeQuery();
            
            while(resultado.next() == true){                
                Livro l = new Livro();
                l.setISBN(resultado.getString(1));
                l.setTitulo(resultado.getString(2));
                l.setAutor(resultado.getString(3));
                l.setEditora(resultado.getString(4));
                l.setAtivo(resultado.getBoolean(5));
                
                livros.add(l);
            }
        }catch(Exception e){
            String erro = "Houve um erro ao ler as informações do Banco de Dados";
            JOptionPane.showMessageDialog(FrameMain.bookFrameCad, erro, "Erro", 0);
            e.printStackTrace();
        }        
        return livros;
    }
    
    public void update(Livro livro, List<LivroExe> listaExe){
        
        Connection con = Conexao.getConnection();
        String sql = "update livro set "
                +"isbn=?, titulo=?, autor=?, editora=?, ativo=? where isbn=?";
                
        try{
            //criando ponto para realizar mudanças de forma experimental
            con.setAutoCommit(false);
            try(PreparedStatement stm = con.prepareStatement(sql)){
                stm.setString(1, livro.getNovoISBN());
                stm.setString(2, livro.getTitulo());
                stm.setString(3, livro.getAutor());
                stm.setString(4, livro.getEditora());
                stm.setBoolean(5, livro.getAtivo());
                stm.setString(6, livro.getISBN());
                
                stm.executeUpdate();
            }
            
            sql = "update livro_exe set "
                    +"pode_emp=? where isbn=? and num_seq=?";
            try(PreparedStatement stm = con.prepareStatement(sql)){
                
                for(LivroExe exe : listaExe){
                    stm.setBoolean(1, exe.getPodeEmprestar());
                    stm.setString(2, exe.getISBN());
                    stm.setInt(3, exe.getNumSequencia());

                    stm.executeUpdate();
                }                
            }
            con.commit();
            
            JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, 
                      "Os dados foram atualizados com sucesso", "Sucesso", 1);
            
        }catch(Exception e){
            try{
                con.rollback();
                String erro = "Houve um erro efetuar a operação no banco de dados";
                JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, erro, "Erro", 0);
                e.printStackTrace();
            }catch(SQLException ex){
                Logger.getLogger(LivroDao.class.getName()).log(Level.SEVERE, null, ex);
            }    
                
        }
    }
    
    public void delete(Livro livro) {
        
        Connection con = Conexao.getConnection();
        String sql = "update livro set "
                +"ativo =? where isbn=?";
        try{    
            con.setAutoCommit(false);
            try(PreparedStatement stm = con.prepareStatement(sql)){                    
                    stm.setBoolean(1, livro.getAtivo());
                    stm.setString(2, livro.getISBN());
                    
                    stm.executeUpdate();
            }
            
            sql = "delete from livro_exe "
                    +"where isbn=? and num_seq > -1";            
            try(PreparedStatement stm = con.prepareStatement(sql)){
                stm.setString(1, livro.getISBN());
                stm.executeUpdate();
            }
            
            con.commit();
            
            JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, 
                      "<html>O livro foi <b color=\"blue\">excluido</b> com sucesso</html>", "Sucesso", 1);
            
        }catch(Exception e){
            try{
                con.rollback();
                String erro = "Houve um erro efetuar a operação no banco de dados";
                JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, erro, "Erro", 0);
                e.printStackTrace();
            }catch(SQLException ex){
                Logger.getLogger(LivroDao.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public void RestaurarLivro(Livro livro, List<LivroExe> listaExe){
        
        Connection con = Conexao.getConnection();
        String sql = "update livro set "
                +"ativo=? where isbn=?";
        try{
            
            con.setAutoCommit(false);            
            try(PreparedStatement stm = con.prepareStatement(sql)){
                stm.setBoolean(1, livro.getAtivo());
                stm.setString(2, livro.getISBN());
                
                stm.executeUpdate();
            }
            
            sql = "insert into livro_exe "
                    +"(isbn, num_seq, emprestado, pode_emp) values (?,?,?,?)";            
            try(PreparedStatement stm = con.prepareStatement(sql)){
                for(LivroExe exe: listaExe){
                    stm.setString(1, exe.getISBN());
                    stm.setInt(2, exe.getNumSequencia());
                    stm.setBoolean(3, exe.getEmprestado());
                    stm.setBoolean(4, exe.getPodeEmprestar());
                    
                    stm.executeUpdate();
                }
            }
            
            con.commit();
            
            JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, 
                      "<html>O livro foi <b color=\"blue\">restaurado</b> com sucesso</html>", "Sucesso", 1);
        }catch(Exception e){
            try{
                con.rollback();
                String erro = "Houve um erro efetuar a operação no banco de dados";
                JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, erro, "Erro", 0);
                e.printStackTrace();
            }catch(SQLException ex){
                Logger.getLogger(LivroDao.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public boolean ExcluirReal(LivroExe exe){
        boolean resp = true;
        Connection con = Conexao.getConnection();
        String sql = "delete from livro_exe "
                +"where isbn=? and num_seq=?";
        try(PreparedStatement stm = con.prepareStatement(sql)){
            stm.setString(1, exe.getISBN());
            stm.setInt(2, exe.getNumSequencia());
            
            stm.executeUpdate();           
        }catch(SQLException e){
                String erro = "Houve um erro efetuar a operação no banco de dados";
                JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, erro, "Erro", 0);
                e.printStackTrace();
                return resp = false;
        }
        
        JOptionPane.showMessageDialog(FrameMain.bookFrameAltera, 
                      "<html>O exemplar foi <b color=\"blue\">excluido</b> com sucesso</html>", "Sucesso", 1);
        return resp;
    }
}
